package com.zenithsun.common.security.session;

import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import com.syzg.base.login.model.LoginObject;
import com.syzg.common.config.SysProperties;
import com.syzg.core.util.DateUtil;

/**
 * session 监听
 * 
 * @author Jiang
 *
 */
public class SessionChangeListener
		implements HttpSessionListener, ServletRequestListener, HttpSessionAttributeListener {
	public static HashMap<String, HttpSession> sessions = new HashMap<>();

	public static synchronized void addSession(HttpSession session) {
		if (session != null) {
			sessions.put(session.getId(), session);
		}
	}

	public static synchronized void delSession(HttpSession session) {
		if (session != null) {
			sessions.remove(session.getId());
		}
	}

	public static synchronized HttpSession getSession(String sessionId) {
		if (sessionId == null) {
			return null;
		}
		return (HttpSession) sessions.get(sessionId);
	}

	/** 以下是实现HttpSessionListener中的方法:该方法登录与否都会执行 **/
	public void sessionCreated(HttpSessionEvent se) {
		System.out.println(DateUtil.formatCurrentDateTime() + ":创建session");
	}

	/** 以下是实现HttpSessionListener中的方法 **/
	@SuppressWarnings("unchecked")
	public void sessionDestroyed(HttpSessionEvent se) {
		ServletContext sc = se.getSession().getServletContext();
		Object session = se.getSession().getAttribute(SysProperties.USER_SESSION_KEY);
		if (session != null) {
			LoginObject loginObject = (LoginObject) session;
			System.out.println(DateUtil.formatCurrentDateTime() + ":" + loginObject.getLogin());
			if (SysProperties.LOGIN_SINGLE) {
				Object obj = sc.getAttribute(SysProperties.USER_ONLINE_LIST);
				Map<String, LoginObject> map;
				if (obj != null) {
					map = (HashMap<String, LoginObject>) obj;
					if (map.containsKey(loginObject.getLogin())) {
						map.remove(loginObject.getLogin());
						sc.setAttribute(SysProperties.USER_ONLINE_LIST, map);
					}
				}
			}
		}
		//销毁session
		HashMap<String, HttpSession> sessionList = new HashMap<>();
		if (sc.getAttribute(SysProperties.USER_SESSION_LIST) != null) {
			sessionList = (HashMap<String, HttpSession>) sc.getAttribute(SysProperties.USER_SESSION_LIST);
		}
		sessionList.remove(se.getSession().getId());
		sc.setAttribute(SysProperties.USER_SESSION_LIST, sessionList);
	}

	public static ServletContext getServletContext() {
		return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest()
				.getServletContext();
	}


	/**
	 * 此方法，可以在登录时候添加一个session 用以判断是否已经登录，然后再进行登录人登录控制
	 */
	@SuppressWarnings("unchecked")
	public void attributeAdded(HttpSessionBindingEvent se) {
		//只处理登录，且为单点登录
		if (SysProperties.USER_SESSION_KEY.equals(se.getName()) && SysProperties.LOGIN_SINGLE) {
			System.out.println(DateUtil.formatCurrentDateTime() + ":" + se.getName());
			ServletContext sc = se.getSession().getServletContext();
			// 记录所有session 便于销毁
			String currentSessionId = se.getSession().getId();
			HashMap<String, HttpSession> sessionList = new HashMap<>();
			if (sc.getAttribute(SysProperties.USER_SESSION_LIST) != null) {
				sessionList = (HashMap<String, HttpSession>) sc.getAttribute(SysProperties.USER_SESSION_LIST);
			}
			// 判断用户是否已经存在
			LoginObject loginObject = (LoginObject) se.getSession().getAttribute(SysProperties.USER_SESSION_KEY);
			
			Map<String, LoginObject> sessionMap = new HashMap<>();
			if (sc.getAttribute(SysProperties.USER_ONLINE_LIST) != null) {
				sessionMap = (HashMap<String, LoginObject>) sc.getAttribute(SysProperties.USER_ONLINE_LIST);
			}
			// 判断用户是否已经登录,根据记录session干掉别处登录的session
			if (sessionMap.containsKey(loginObject.getLogin())) {
				LoginObject oldLogin = sessionMap.get(loginObject.getLogin());
				String sessionId = oldLogin.getSessionId();
				HttpSession hs = sessionList.get(sessionId);
				if (hs != null) {
					System.out.println(DateUtil.formatCurrentDateTime() + 
							":[" + loginObject.getLogin() + "]被强制在终止"+loginObject.getIp()+"下线");
					hs.invalidate();
				}
				sessionList.remove(sessionId);
			} else {
				//正常登陆
				System.out.println(DateUtil.formatCurrentDateTime() + ":[" + loginObject.getLogin() + "]登录系统");
			}
			//重新记录登录用户
			loginObject.setSessionId(currentSessionId);
			sessionMap.put(loginObject.getLogin(), loginObject);
			sc.setAttribute(SysProperties.USER_ONLINE_LIST,sessionMap);
			//记录所有用户的session 便于销毁
			sessionList.put(currentSessionId, se.getSession());
			sc.setAttribute(SysProperties.USER_SESSION_LIST, sessionList);
		}
	}

	public void attributeRemoved(HttpSessionBindingEvent event) {
		// TODO Auto-generated method stub
	}

	public void attributeReplaced(HttpSessionBindingEvent arg0) {
		// TODO Auto-generated method stub
	}

	public void requestDestroyed(ServletRequestEvent arg0) {
		// TODO Auto-generated method stub
	}

	@Override
	public void requestInitialized(ServletRequestEvent arg0) {
		// TODO Auto-generated method stub

	}

}
